import sys
import pdb
import threading
import heartbeating
import MSSafeinsideLib as lib
log = lib.log
g_name = 'ms driver'

log.info(g_name + ' starting as %s' % (str(sys.argv)))

try:
    heartbeat = heartbeating.HeartbeatListener(int(lib.MSConfig.getConfig().get('main', 'heartbeat_port')))
    heartbeat.start()
except Exception, err:
    log.error('can\'t start ' + g_name + ' at port ' + lib.MSConfig.getConfig().get('main', 'heartbeat_port') + ', probably another instance is running')
    log.error('code: %s', str(err))
    sys.exit(1)

def processNormalObjects(isTerminated, dummy):
    log.info('processNormalObjects: started')

    try:
        cfg = lib.MSConfig.getConfig()
        reader = lib.MSDBReader(cfg.get('msdb', 'host'),
                                cfg.get('msdb', 'port'),
                                cfg.get('msdb', 'dbname'),
                                cfg.get('msdb', 'user'),
                                cfg.get('msdb', 'pwd'))
        reader.connect()

        writer = lib.PCNFBWriter(cfg.get('pcnfb', 'path'),
                                 cfg.get('pcnfb', 'user'),
                                 cfg.get('pcnfb', 'pwd'))
        writer.connect()
    except Exception, err:
        log.info('processNormalObjects: can\'t start: %s', str(err))
        return

    objects = {}
    ctr = 0
    lastEventId = 0

    try:
        while not isTerminated.isSet():
            if (ctr % 100 == 0):
                try:
                    lib.MSObjects.readObjectsFromMSDB(reader.connection.cursor(), objects, 'dev')
                    log.info('processNormalObjects: loaded %d objects', len(objects))
                except Exception, err:
                    log.error('processNormalObjects: can\'t load objects: %s', str(err))
                log.info('processNormalObjects: status format: all:pgsm:cid:bolid:written')
            allevents = []
            ids = None
            eventsPGSM = None
            eventsContactId = None
            eventsBolid = None
            written = 0
            try:
                ids, eventsPGSM, lastEventId = reader.getEventsPGSM(objects, lastEventId)
                allevents += eventsPGSM
                eventsContactId = reader.getEventsContactId(ids, objects)
                allevents += eventsContactId
                eventsBolid     = reader.getEventsBolid(ids, objects)
                allevents += eventsBolid
            except Exception, err:
                log.error('processNormalObjects: can\'t read events: %s', str(err))

            try:
                written = writer.writeEventsStatic(allevents)
            except Exception, err:
                log.error('processNormalObjects: can\'t write events: %s', str(err))

            try:
                #lastEventId = reader.finalyzeEvents(ids)
                for lastEventId in ids: pass
            except Exception, err:
                log.error('processNormalObjects: can\'t finalyze: %s', str(err))
            log.info('processNormalObjects: %d:%d:%d:%d:%d lastid(%d)', len(ids), len(eventsPGSM), len(eventsContactId), len(eventsBolid), written, lastEventId)
            ctr += 1
            if written == 0: lib.time.sleep(5)
    except Exception, err:
        log.error('processNormalObjects: fatal error: %s' % (str(err)))

def processAPIObjects(isTerminated, dummy):
    log.info('processAPIObjects: started')

    try:
        cfg = lib.MSConfig.getConfig()
        reader = lib.MSAPIReader(cfg.get('msapi', 'url'))
        writer = lib.PCNFBWriter(cfg.get('pcnfb', 'path'),
                                 cfg.get('pcnfb', 'user'),
                                 cfg.get('pcnfb', 'pwd'))
        writer.connect()
    except Exception, err:
        log.info('processAPIObjects: can\'t start: %s', str(err))
        return

    objects = {}
    ctr = 0
    lastEventId = 0

    try:
        while not isTerminated.isSet():
            if (ctr % 100 == 0):
                try:
                    lib.MSObjects.readObjectsFromFile(cfg.get('msapi', 'objects_cfg'), objects)
                    log.info('processAPIObjects: loaded %d objects from %s', len(objects), cfg.get('msapi', 'objects_cfg'))
                except Exception, err:
                    log.error('processAPIObjects: can\'t load objects: %s', str(err))
                log.info('processAPIObjects: status format: all:pgsm:cid:written')
            allevents = []
            ids = None
            eventsPGSM = None
            eventsContactId = None
            written = 0
            try:
                ids, eventsPGSM, lastEventId = reader.getEventsPGSM(objects, lastEventId)
                allevents += eventsPGSM
                eventsContactId = reader.getEventsContactId(ids, objects, lastEventId)
                allevents += eventsContactId
            except Exception, err:
                log.error('processAPIObjects: can\'t read events: %s', str(err))

            try:
                written = writer.writeEventsStatic(allevents)
            except Exception, err:
                log.error('processAPIObjects: can\'t write events: %s', str(err))

            for lastEventId in ids: pass
            log.info('processAPIObjects: %d:%d:%d:%d lastid(%d)', len(ids), len(eventsPGSM), len(eventsContactId), written, lastEventId)
            ctr += 1
            if written == 0: lib.time.sleep(5)
    except Exception, err:
        log.error('processAPIObjects: fatal error: %s' % (str(err)))


log.info('starting threads... ')
isTerminated = threading.Event()
isTerminated.clear()

normalObjectsFromMSDB   = threading.Thread(target=processNormalObjects, name='normalObjectsFromMSDB', args=(isTerminated, None))
normalObjectsFromMSAPI  = threading.Thread(target=processAPIObjects, name='normalObjectsFromMSAPI', args=(isTerminated, None))
try:
    #start them
    normalObjectsFromMSDB.start()
    normalObjectsFromMSAPI.start()
    #check them
    lib.time.sleep(5)
    if not normalObjectsFromMSDB.isAlive(): raise RuntimeError('normalObjectsFromMSDB is not alive')
    if not normalObjectsFromMSAPI.isAlive(): raise RuntimeError('normalObjectsFromMSAPI is not alive')
except Exception, err:
    log.error('can\'t start threads: ', str(err))
    sys.exit(2)

log.info(g_name + ' started. Waiting for stop signal...')
try:
    while True: lib.time.sleep(10)
except KeyboardInterrupt:
    log.info(g_name + ' stopping: %s' % (str(sys.argv)))
    sys.exit(0)
except Exception, err:
    log.error(g_name + ' stopping, fatal error: %s' % (str(err)))
    sys.exit(5)
finally:
    try:
        isTerminated.set()
        normalObjectsFromMSDB.join()
        normalObjectsFromMSAPI.join()
        heartbeat.stop()
        log.info('stopped')
    except Exception, err:
        log.error('error while exiting: %s', str(err))
        sys.exit(4)
